/******************************************************************************
 * Copyright (C) 2025 COMPANY or its affiliates.
 * 
 * All Rights Reserved.
 * 
 @file w25qxx_handler.c
 * 
 @par dependencies 
 - w25qxx_handler.h  // 对应头文件
 * 
 @author liubin | R&D Dept. | COMPANY
 * 
 @brief 模块核心功能实现，包括：
            - 功能点1：xxx初始化与配置
            - 功能点2：xxx数据处理与交互
            - 功能点3：xxx资源管理与释放
 * 
 Processing flow:
 * 1. 初始化阶段：
            - 调用xxx_init()完成硬件/软件初始化
            - 初始化全局变量与静态变量
            - 注册回调函数（如需要）
 * 2. 运行阶段：
            - 接收输入数据（如xxx_rx()）
            - 调用核心处理函数（如xxx_process()）
            - 输出处理结果（如xxx_tx()）
 * 3. 销毁阶段：
            - 调用xxx_deinit()释放资源
            - 重置变量状态（如需要）
 * 
 @version V1.0 2025-11-09
 *
 @note 1 tab == 4 spaces!
 *       - 实现说明：如使用DMA传输、中断优先级配置
 *       - 性能限制：如最大处理速率、内存占用上限
 *       - 调试提示：关键日志输出位置、断点设置建议
 *
 *****************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "w25qxx_Handler.h"
#include "w25qxx.h"
//#include "SEGGER_RTT.h"
#include "elog.h"
/* Private typedef -----------------------------------------------------------*/

static w25qxx_handler_t w25qxx_handler_1;


/* Private define ------------------------------------------------------------*/


/* Private macro -------------------------------------------------------------*/


/* Private variables ---------------------------------------------------------*/


/* Global variables ----------------------------------------------------------*/


/* Private function prototypes -----------------------------------------------*/


/* Global function prototypes -------------------------------------------------*/


/* Private functions ---------------------------------------------------------*/

static void W25Q64_Data_init()
{
	w25qxx_handler_1.read_index = 1;
  w25qxx_handler_1.read_sector_index = 1;
  w25qxx_handler_1.write_databuff_index = 1;
  w25qxx_handler_1.write_index = 1;
  w25qxx_handler_1.write_sector_index = 1;
	//跳过第一个4k位置
}

/* Global functions ----------------------------------------------------------*/

void W25Q64_Init(void)
{
    W25Qx_Init();
		elog_i("w25qxx","id:%x",W25Qx_Para.FLASH_ID);
    W25Q64_Data_init();
}

uint8_t W25Q64_EraseChip(void)
{
    if(0 == W25Qx_Erase_Chip())
    {
        W25Q64_Data_init();
        return 0;
    }
    return 1;
}

uint8_t W25Q64_WriteData(uint8_t *data, uint32_t length)
{
    // uint8_t ret = 0;
    uint32_t addr = 0;
    uint16_t index = 0;
    for(uint32_t i = 0; i < length; i++)
    {
        //1.数据写入数据缓冲区里面
        index = w25qxx_handler_1.write_databuff_index;
        w25qxx_handler_1.databuff[index] = *(data + i);
        w25qxx_handler_1.write_databuff_index++;
        //2.判断数据有没有写满4096
        if(w25qxx_handler_1.write_databuff_index == W25Qx_Para.SUBSECTOR_SIZE)
        {
            w25qxx_handler_1.write_databuff_index = 0;
            //擦除1个sector
            addr = W25Qx_Para.SUBSECTOR_SIZE * w25qxx_handler_1.write_sector_index;
            W25Qx_Erase_Block(addr);
            W25Qx_WriteEnable();
            //写满了一个sector，执行写入操作   4096个byte
            for(uint8_t j = 0; j < 16; j++)
            {
                //获取当前写入地址
                addr = (W25Qx_Para.SUBSECTOR_SIZE * w25qxx_handler_1.write_sector_index) + \
                        (W25Qx_Para.PAGE_SIZE * j);
                //执行写入操作
                index = W25Qx_Para.PAGE_SIZE * j;
                W25Qx_Write(&w25qxx_handler_1.databuff[index],addr,W25Qx_Para.PAGE_SIZE);
            }
            w25qxx_handler_1.write_sector_index++;
            //记录总的写入数据长度
            w25qxx_handler_1.write_index += W25Qx_Para.SUBSECTOR_SIZE;
        }
    }
    return 0;
}

uint8_t W25Q64_WriteDataEnd(void)
{
    uint32_t addr = 0;
    uint16_t index = 0;
    uint8_t  page_size = 0;
    //判断还有没有剩余数据没有执行写入
    if(0 != w25qxx_handler_1.write_databuff_index)
    {
        //写入次数
        page_size = w25qxx_handler_1.write_databuff_index / W25Qx_Para.PAGE_SIZE;
        //先执行擦除扇区
        addr = W25Qx_Para.SUBSECTOR_SIZE * w25qxx_handler_1.write_sector_index;
        W25Qx_Erase_Block(addr);
        W25Qx_WriteEnable();
        for(uint8_t j = 0; j < page_size; j++)
        {
            //获取当前写入地址
            addr = (W25Qx_Para.SUBSECTOR_SIZE * w25qxx_handler_1.write_sector_index) + \
                    (W25Qx_Para.PAGE_SIZE * j);
            //执行写入操作
            index = W25Qx_Para.PAGE_SIZE * j;
            W25Qx_Write(&w25qxx_handler_1.databuff[index],addr,W25Qx_Para.PAGE_SIZE);
        }

        //有没有小于256的数据了
        if(0 != (w25qxx_handler_1.write_databuff_index % W25Qx_Para.PAGE_SIZE))
        {
            //获取当前写入地址
            addr = (W25Qx_Para.SUBSECTOR_SIZE * w25qxx_handler_1.write_sector_index) + \
                    (W25Qx_Para.PAGE_SIZE * page_size);
            //执行写入操作
            index = W25Qx_Para.PAGE_SIZE * page_size;
            W25Qx_Write(&w25qxx_handler_1.databuff[index],addr, \
                        w25qxx_handler_1.write_databuff_index % W25Qx_Para.PAGE_SIZE);
        }
        w25qxx_handler_1.write_index += w25qxx_handler_1.write_databuff_index;
    }
    return 0;
}

/*每次读取一个扇区的数据，外部接口需要一个4096的buffer
length:每次读取出来的长度，从缓冲区读取
return : 
        0:表示读取成功
        1:读取完毕  没有数据了
        2:读取失败  读取错误
*/
uint8_t W25Q64_ReadData(uint8_t *data, uint16_t *length)
{
    // uint8_t ret = 0;
    uint32_t addr = 0;
    // uint16_t index = 0;
    // uint8_t  page_size = 0;
    // uint16_t  remain_size = 0;

    //1.先判断是否读取完毕
    if(w25qxx_handler_1.write_index > w25qxx_handler_1.read_index)
    {
        //判断下数据是否够4K
        if(w25qxx_handler_1.write_sector_index > w25qxx_handler_1.read_sector_index)
        {
            //读4K数据的操作
            *length = W25Qx_Para.SUBSECTOR_SIZE;
            addr = w25qxx_handler_1.read_sector_index * W25Qx_Para.SUBSECTOR_SIZE;
            if(0 != W25Qx_Read(data,addr,*length))
                return 2;
            w25qxx_handler_1.read_sector_index++;
        }
        else
        {
            //读4K以内的数据
            *length = w25qxx_handler_1.write_index - w25qxx_handler_1.read_index;
            addr = w25qxx_handler_1.read_sector_index * W25Qx_Para.SUBSECTOR_SIZE;
            if(0 != W25Qx_Read(data,addr,*length))
                return 2;
        }
        w25qxx_handler_1.read_index += *length;
        return 0;
    }
    else
    {
        return 1;
    }
}